了解JS对象的属性的特性 您所在的位置:网站首页 js 修改对象的属性名字 了解JS对象的属性的特性

了解JS对象的属性的特性

2023-05-26 01:25| 来源: 网络整理| 查看: 265

一 对象属性的特性

对于对象中的属性,除了可以对其赋值以外,每一个属性的内部都包含有一些内部特性来描述属性自身的特征的。 这些内部特性,开发者是无法直接访问的,只能通过 Object.defineProperty() 这个函数来对其进行修改。 不同的对象属性又有不同的内部特性,这里分开来介绍。对象的属性分两种:数据属性和访问器属性。

1 数据属性

数据属性就是最普通的属性,包含一个保存数据的位置。值都在同一个地方读写,比如这里的 name 就是一个数据属性:

1665653590475(1).jpg 这种属性有四个特性描述他们的行为:

1). configurable “可配置的” 默认值:true

作用:

是否可以通过 delete 删除并重新定义 是否可以修改其特性 是否可以把它改为访问器属性。 解释:

如果把 configurable 设置成 false,就意味着这个属性不能在对象上删除。非严格模式下对这个属性调用 delete 没有效果(返回 false),严格模式下会抛出错误。

而且,当一个属性被设置为不可配置之后,就不能再设置回可配置的了,也无法修改其他内部特性,因为 Object.defineProperty() 无法对 configurable 值为 false 的属性进行修改。

2). enumerable “可列举的” 默认值:true

作用:是否可以通过 for-in 循环返回。(for-in 循环可以列举对象的属性)

3). writable “可写的” 默认值:true

作用:它的值(也就是👇下面的 value 属性)是否可被修改。

4). value “值” 默认值:undefined

作用:属性实际的值。

在👆上面 person.name 这个示例属性中,它的 value 就为 "对象属性"。

1.1 修改方法

Object.defineProperty() 需要传入三个参数,第一个是需要修改属性的对象,第二个是属性的名称,第三个是需要修改的特性的集合。

例如我想把 name 属性修改为不可枚举且不可修改:

1665653630825.jpg

函数的第三个参数只需传入需要修改的特性和值即可,对于没传入的特性,比如上面没有传入的 configurable 和 value 这两个特性将会保持原有值不变。

如果第二个参数传入的属性名是对象上没有的属性,就会为那个对象添加一个属性。例如:

1665653655656.jpg

2访问器属性

访问器属性不包含数据值,取而代之的是一个 getter 函数和一个 setter 函数,不过这两个函数都不是必须的。

在读取访问器属性时,会调用 getter 函数,并返回函数的返回值。

在写入访问器属性的时候,会调用 setter 函数,并传入新值,由 setter 函数来决定如何处理这个新值。

访问器属性也有四个特性,其中 configurable 和 enumerable 特性和数据属性是一样的,不同的是另外两个特性被 get 和 set 取代:

1). configurable “可配置的” 默认值:true

作用:👆同数据属性一样。

2). enumerable “可列举的” 默认值:true

作用:👆同数据属性一样。

3). get “获取函数” 默认值:undefined

作用:获取函数,在读取属性时调用。

4). set “设置函数” 默认值:undefined

作用:设置函数,在写入属性时调用。

1665653684300.jpg

2.1修改方法

同数据属性类似,访问器属性的特性也是通过 Object.defineProperty() 来定义的:

1665653823646.jpg

二.对象序列化? 1).什么是对象序列化?

对象序列化是指将对象的状态转换为字符串;

序列化(Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程;

2).为什么会有对象序列化?

1665653845436.jpg

当这句代码运行时,对象obj的内容会存储在一块内存中,而obj本身存储的只是这块内存的地址的映射而已。简单的说,对象obj就是我们的程序在电脑通电时在内存中维护的一种东西,如果我们程序停止了或者电脑断电了,对象obj将不复存在。那么如何把对象obj的内容保存在磁盘上呢(也就是说在没电时继续保留着)?这时就需要把对象obj序列化,也就是说把obj的内容转换成一个字符串的形式,然后再保存在磁盘上。另外,我们又怎么通过HTTP协议把对象obj的内容发送到客户端呢?没错,还是需要先把对象obj序列化,然后客户端根据接收到的字符串再反序列化(也就是将字符串还原为对象)解析出相应的对象。这也正是”百度百科—序列化“中描述的两个作用——存储、传输。

1 JSON.stringify() 1.1.简介

序列化原始值、对象或数组

1.2.概要

JSON.stringify(o[, filter][, indent])

1.3.参数

o,要转换成JSON字符串的原始值、对象或数组

filter,可选参数,一个数组或函数

indent,可选参数,一个数值或一个字符串

1.4.返回

JSON格式的字符串,代表o的值,同时通过了filter的过滤,以及根据indent进行了格式化

1.5.描述

①当对象o自身带有toJSON()方法时,JSON.stringify()会调用o的toJSON()方法,并使用该方法的返回值而不是该对象本身进行字符串化;

②如果filter存在且是一个函数,那么该函数的返回值将会作为JSON.stringify()方法的返回值。并且该函数接收两个参数,第一个参数是一个空字符串,第二个参数就是对象o。这里,大家也可以参考Douglas Crockford为 ES3 环境使用JSON写的json2:

③如果filter存在且是一个字符串数组(如果数组中包含数字,数字会自动转化为字符串),那么对象o的某些属性名如果不在这个数组中,则序列化时会将这些属性省略,且返回的字符串中属性的顺序会与该数组中属性的顺序一致;

④JSON.stringify()返回的通常是不带任何空格或换行符的字符串。如果想输出可读性更好的字符串,需要指定第三个参数。如果指定的第三个参数是介于1~10之间的值,则JSON.stringify()会在每一“层级”的输出插入换行符和指定个数的空格。如果指定的第三个参数是非空字符串,则JSON.stringify()会插入换行符和该字符串(只取前十个字符)来缩进层级;

2 JSON.parse() 2.1.简介

解析JSON格式的字符串

2.2.概要

JSON.parse(s[, reviver])

2.3.参数

s,要解析的字符串

reviver,可选参数,用来转换解析值的可选函数

2.4.返回

一个对象、数组或原始值。该返回值是从s中解析的(还有可能被reviver修改过);

2.5.描述

①如果指定了reviver函数,该函数会为从s中解析的每一个原始值(不是包含这些原始值的对象或数组)调用一次。调用reviver时带有两个参数,第一个参数是属性名——对象的属性名或转换成字符串的数组序号,第二个参数是对象属性或数组元素的原始值。并且,reviver函数的返回值将作为JSON.parse()的返回值;

三 对象原型链

1 函数与对象的关系 函数是对象,对象都是通过函数创建的。 函数与对象并不是简单的包含与被包含的关系。

2 原型的类别 显示原型:prototype,是每个函数function独有的属性。 隐式原型: proto,是每个对象都具有的属性。

3 原型和原型链

原型:一个函数可以看成一个类,原型是所有类都有的一个属性,原型的作用就是给这个类的一个对象都添加一个统一的方法。 原型链:每个对象都有一个__proto__,它指向它的prototype原型对象;它的prototype原型对象又有一个__proto__指向它的prototype原型对象,就这样层层向上直到最终找到顶级对象Object的prototype,这个查询路径就是原型链。

四 对象的数据存储

1 对象数据存储在堆栈中。栈的数据读取,写入速度快,但是存储的内容较少。堆的读取和写入速度慢,但是存储的内容多。举个例子来说就像电脑中内存和硬盘,内存就像栈,需要经常获取,写入速度比较快时需要写道内存也就是需要存储在栈中的数据,其中字符型,数值型,布尔型,undefined存储在栈中,栈中,一旦该变量不再使用时就会被清理掉。而对象是存储在堆中,当堆中有对象时,它会相对应内存中有一个存储的地址,在栈中obj存储了在堆中数据的地址,当调用数据时,去堆中调取对应堆中的数据的地址获取出来。

1665653878807.jpg 2 如上,代码执行时一行接着一行,先创建一个对象,打印在控制台后,把obj的a值改为10,在控制台点开对象前的箭头时,obj的a值却已经更改为10,这就是我们在打印后去更改,可在去点击箭头时,才会去堆中对应地址获取数据,所以获取的就是最新的数据。

1665653900228.jpg

3 如上,如果将obj赋值给obj1,就相当于把obj在堆中存储数据的地址给到obj1,obj1更改对象原有的数据时,obj也会跟着更改

1665653973863(1).jpg

4 如上,如果将obj赋值给obj2,但在obj生成新对象时,就会在栈中创建一个新的存储数据的地址,所以后更改对象数据时更改到就是新的存储数据的地址中,而obj2的存储数据地址还是原来的对象地址,所以打印后只有对象在没有生成新对象之前的堆中地址存储的数据。

1665653998247.jpg

5 如上,如果将obj赋值给obj3,两个对象在堆中存储地址相同时,我们两个对象都不想去使用时,把堆中对象存储的地址丢弃时,该数据在堆中存在,并且找不到它,当如此情况非常多时,称之为内存泄漏,会造成卡死,想要解决掉这个问题,

就需要把对象堆中存储数据地址的所有引用对象全部先设置为null,之后再去重新赋值


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有